<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/3/19 0019
 * Time: 11:23
 */

namespace app\currency\service;


use think\Db;

class AccessTokenService
{
    const ACCESS_TOKEN_DEFECT_CODE = 401;//Token缺失
    const ACCESS_TOKEN_DEFECT_DESC = 'access_token缺失！';
    const ACCESS_TOKEN_INVALID_CODE = 403;//Token无效
    const ACCESS_TOKEN_INVALID_DESC = 'access_token无效！';
    const ACCESS_TOKEN_OVERDUE_CODE = 403;//Token过期
    const ACCESS_TOKEN_OVERDUE_DESC = 'access_token过期！';
    const REFRESH_TOKEN_DEFECT_CODE = 402;

    /**
     * 生成凭证
     * @param int $mid
     * @param string $client
     * @return array
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public static function createAccessToken($mid = 0, $client = 'member'){
        if(!in_array($client,['member','cleaner','agent']))
        {
            throw new \think\Exception("client {$client} not found");
        }
        //生成access_token和refresh_token
        list($access_token,$refresh_token) = [getGuid(),getGuid()];
        //存储access_token
        data_save('AccessTokens', [
            'access_token'   => $access_token,
            'client' => $client,
            'user_id' => $mid,
        ], 'user_id',['client' => $client]);
        //存储refresh_token
        data_save('RefreshTokens', [
            'refresh_token'   => $refresh_token,
            'client' => $client,
            'user_id' => $mid,
        ], 'user_id',['client' => $client]);
        $result = [
            'access_token' => $access_token,
            'refresh_token' => $refresh_token,
        ];
        return $result;
    }

    /**
     * 刷新登陆凭证
     * @param string $refresh_token
     * @param string $client
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public static function refreshToken($refresh_token = '', $client = 'member'){
        if($refresh_token == '') {
            return ['code' => self::ACCESS_TOKEN_DEFECT_CODE,'msg' => 'refresh_token缺失！'];
        }
        if(!in_array($client,['member','cleaner','agent']))
        {
            throw new \think\Exception("client {$client} not found");
        }
        // 查询refresh_token
        $info = Db::name('RefreshTokens')->where([['refresh_token','eq',$refresh_token],['client','eq',$client]])->find();
        // 检测refresh_token 是否存在
        if(empty($info)){
            return ['code' => self::ACCESS_TOKEN_DEFECT_CODE,'msg' => 'refresh_token无效！'];
        }
        // 检测refresh_token 是否过期
        if(strtotime($info['expire_in']) < strtotime('-30 day')){
            return ['code' => self::ACCESS_TOKEN_DEFECT_CODE,'msg' => 'refresh_token过期！'];
        }
        // 开始刷新
        $access_token = getGuid();
        //存储access_token
        data_save('AccessTokens', [
            'access_token'   => $access_token,
            'client' => $client,
            'user_id' => $info['user_id'],
        ], 'user_id',['client' => $client]);
        // 判断是否需要同步刷新refresh_token 剩余两天内
        if(strtotime($info['expire_in']) < strtotime('-28 day')){
            // 开始刷新
            $refresh_token = getGuid();
            //存储refresh_token
            data_save('RefreshTokens', [
                'refresh_token'   => $refresh_token,
                'client' => $client,
                'user_id' => $info['user_id'],
            ], 'user_id',['client' => $client]);
        }
        $result = [
            'access_token' => $access_token,
            'refresh_token' => $refresh_token,
        ];
        return $result;
    }

    /**
     * 检测凭证
     * @param string $access_token
     * @param string $client
     * @return array|mixed
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function checkAccessToken($access_token = '', $client = 'member'){
        if($access_token == '') {
            return ['code' => self::ACCESS_TOKEN_DEFECT_CODE,'msg' => self::ACCESS_TOKEN_DEFECT_DESC];
        }
        if(!in_array($client,['member','cleaner','agent']))
        {
            throw new \think\Exception("client {$client} not found");
        }
        $info = Db::name('AccessTokens')->where([['access_token','eq',$access_token],['client','eq',$client]])->find();
        // 检查token是否存在
        if(empty($info)) {
            return ['code' => self::ACCESS_TOKEN_INVALID_CODE,'msg' => self::ACCESS_TOKEN_INVALID_DESC];
        }
        // 检测access_token 是否过期
        if(strtotime($info['expire_in']) < strtotime('-3 day')){
            return ['code' => self::ACCESS_TOKEN_OVERDUE_CODE,'msg' => self::ACCESS_TOKEN_OVERDUE_DESC];
        }
        return $info['user_id'];
    }
}